/**
 * Editor module
 */

import React from 'react';
import {connect} from 'redux';

import eventHelper from '../../../util/EventHelper';
import Phone from './Phone';
import Preview from './Preview';
import Widget from './Widget';
import Ruler from './Ruler';
import storage from '../../../util/storage';
import consts from '../../../util/consts';
import tool from '../../../util/tool';

import dataProvider from '../provider/dataProvider';
import contextMenuProvider from '../provider/contextMenuProvider';
import zoomProvider from '../provider/zoomProvider';
import historyProvider from '../provider/historyProvider';

const mapStateToProps = ({editor, widgets}) => {
    return {
        scale: editor.scale,
        preview: editor.preview,
        widgets,
        centerTop: editor.centerTop,
        centerLeft: editor.centerTop,
        switchType: editor.switchType,
        selectedWidgetId: editor.selectedWidgetId
    };
};

const Editor = React.createClass({
    componentDidMount() {
        // 初始化所有的dom节点
        this.initElements();
        // 初始化所有的dom容器
        this.initContainer();
        // 绑定所有特定的事件
        this.bindEvent();

        let root = this.props.root,
            fromTemplate = this.props.fromTemplate;
        if (!fromTemplate) {
            root.handleOnSortable(this.elements.floating_container, 'y');
        }
    },
    initElements() {
        this.elements = {
            canvas: $('.editor-canvas'),
            lineCanvas: $('.lineCanvas'),
            snap_theme: $('.snap_theme'),
            editor_right: $('.Editor-right'),
            editorPanel: $('.creator-editor'),
            container: $(this.refs['container']),
            creator_editor: $('.creator-editor'),
            editorMainImg: $('.editor-main-img'),
            editorMainPhone: $('.editor-main-phone'),
            editorPos: $('.editor-canvas.editor_test'),
            floating_container: $('.floating_container'),
            template_content_region: $('.template-content-region'),
            template_property_content: $('.template-property-content'), // 模板AR property
        };
    },
    initContainer() {
        const _const = storage.data.CONST;
        let scrollTop = _const.view.height / 2 - 700,
            scrollLeft = _const.view.width / 2 - 700;
        const area = {
            width: parseFloat(_const.editor_width),
            height: parseFloat(_const.editor_height)
        };
        const top = scrollTop + this.elements.editorPanel.height() / 2 - area.height / 2;
        const left = scrollLeft + this.elements.editorPanel.width() / 2 - area.width / 2;

        const root = this.props.root;
        root.setState({centerTop: top, centerLeft: left});

        const mainImgPosition = {
            left,
            top
        };
        // set transform
        this.transform = {
            offset_x: mainImgPosition.left + area.width / 2,
            offset_y: mainImgPosition.top + area.height / 2
        };

        // reset canvas size
        this.elements.editorPos.css(storage.data.CONST.view);
        // reset the phone background img to center position
        this.elements.editorMainPhone.css({
            'margin-top': -94 - (765 - area.height) / 2,
            left: scrollLeft + this.elements.editorPanel.width() / 2 - area.width / 2,
            top: scrollTop + this.elements.editorPanel.height() / 2 - area.height / 2
        });
        // scroll to the center position
        this.elements.editorPanel.scrollTop(scrollTop);
        this.elements.editorPanel.scrollLeft(scrollLeft);
        // reset main img position
        this.elements.editorMainImg.css(mainImgPosition);
        // reset line canvas position
        this.elements.lineCanvas.css(mainImgPosition);
        // reset snap_theme position
        this.elements.snap_theme.css({
            width: area.width,
            height: _const.resource_type == 0 && area.height > 757
                ? '757px'
                : area.height,
            left: scrollLeft + this.elements.editorPanel.width() / 2 - area.width / 2,
            top: _const.resource_type == 0 && area.height > 757
                ? scrollTop + this.elements.editorPanel.height() / 2 - 759.0 / 2
                : scrollTop + this.elements.editorPanel.height() / 2 - area.height / 2
        });
        this.elements.snap_theme.draggable();
    },
    bindEvent() {
        var root = this.props.root,
            fromTemplate = this.props.fromTemplate;
        let data = storage.data,
            selecting = false;
        let contextmenuClass = 'editor-context-menu',
            NS = '.FIT_PAGE_AREA';
        var fromTemplate = this.props.fromTemplate;

        this.elements.canvas.off(`click${NS}`);
        this.elements.canvas.on(`click${NS}`, (ev) => {
            if (selecting)
                return;
            let target = $(ev.target),
                widget = target.closest('.btg-widget');
            const indoc = $.contains(document.documentElement, ev.target);
            let widgetId = widget.length
                ? (widget.attr('data-id'))
                : null;
            let showFloatingHead = false;

            const isShift = this.isKeyPressed(ev); // shift键是否按下
            if (!indoc || !ev.target)
                return;
            if (target.closest('.widget-form, .ui-tooltip').length)
                return;

            $('.zoom-tool .ui-slider-handle').blur();
            $('.addfloatingbtns .btn-eidt-widget-event').blur();

            data.selectedWidgetIds = isShift
                ? data.selectedWidgetIds || []
                : [];
            data.selectedWidgetId = null;

            const root = this.props.root;
            root.onEditModeChange(consts.EDIT_MODE.PAGE);
            let focusTab = consts.FOCUS_TABS.PAGE;
            // 取消选中
            eventHelper.trigger(consts.EVENTS.THREED_WIDGET_SELECTED);
            if (!widgetId) {
                if (data.editMode == consts.EDIT_MODE.TEXT)
                    return;
                if (data.editMode == consts.EDIT_MODE.ANIMATION)
                    return;

                this.elements.canvas.data('context').closemenu();
                this.refs.widget && this.refs.widget.elements.widget.data('context').closemenu();
                if (!fromTemplate && $(this.refs.Ruler.refs.lines).length) {
                    $(this.refs.Ruler.refs.lines).data('context').closemenu();
                }
                storage.data.shiftKey = '';
                data.selectedWidgetIds = [];
            } else {
                storage.addSelectedWidgetId(widgetId, isShift);
                widgetId = isShift
                    ? data.selectedWidgetIds[data.selectedWidgetIds.length - 1] || null
                    : widgetId;
                data.selectedWidgetId = widgetId;
                data.selectedWidgetTimelineId = null;
                focusTab = tool.checkWidgetType(widgetId, dataProvider, this.props.timelines, () => {
                    this.twinkling();
                });
                var selectedWidget = dataProvider.getSpecifyWidgetById(widgetId);
                if (selectedWidget) {
                    if (selectedWidget.type == consts.WIDGET_TYPE.FIXEDBTN && focusTab == consts.FOCUS_TABS.EVENT) {
                        showFloatingHead = true;
                    }

                    this.handleOnPlayVideo(selectedWidget);
                    if (fromTemplate)
                        this.TemplatePropertyPosition(widgetId);

                    // 选中
                    eventHelper.trigger(consts.EVENTS.THREED_WIDGET_SELECTED, widgetId);
                }
            }
            root.updateState(data.page.page_id, data.selectedWidgetIds, {
                focusTab,
                showFloatingHead,
                preview: {
                    showPreview: false
                },
                selectedWidget
            });
        });

        const directions = {
            37: 'offset_x',
            38: 'offset_y',
            39: 'offset_x',
            40: 'offset_y'
        };
        const offsets = {
            37: -1,
            38: 1,
            39: 1,
            40: -1
        };
        const keyCodes = {
            delete: 46,
            enter: 13,
            backspace: 8, // 适配mac删除
            c: 67,
            v: 86,
            z: 90
        };
        const self = this;
        // 方向键位移组件
        $(document).keydown((e) => {
            const code = e.keyCode;
            // 修复input输入框敲回车跳转问题
            if (code === keyCodes.enter && e.target.nodeName === 'INPUT') {
                e.stopPropagation();
                e.preventDefault();
                return false;
            }
            //　防止混淆输入框中的事件
            if (e.target === document.body) {
                const id = data.selectedWidgetId;
                const widget = dataProvider.getSpecifyWidgetById(id);

                storage.data.shiftKey = '';

                // delete键删除
                if (code === keyCodes.delete || code === keyCodes.backspace) {
                    self.deleteSeletedWidget(id);
                    return false;
                }
                if (e.keyCode == keyCodes.z && e.ctrlKey) {
                    if (historyProvider.canUndo()) {
                        historyProvider.undo();
                    }
                    return false;
                }
                const selectedWidgetIds = data.selectedWidgetIds;
                if (selectedWidgetIds) {
                    if (e.keyCode == keyCodes.c && e.ctrlKey) {
                        console.log('ctrl+c');
                        self.copyWidgets();
                        return false;
                    }
                    if (e.keyCode == keyCodes.v && e.ctrlKey) {
                        console.log('ctrl+v');
                        self.pasteWidgets();
                        return false;
                    }
                }
                if (widget) {
                    let property = widget[directions[code]];
                    property += offsets[code];

                    widget[directions[code]] = property;
                    root.updateSpecifyWidget(widget);
                    return false;
                }
            }
        });

        this.contextmenu = this.elements.canvas.contextmenu({target: `.${contextmenuClass}`, onItem: this.handleOnContextMenu});
        if (fromTemplate)
            root.updateMenus('editor');

        this.elements.canvas.selectable({
            filter: '.btg-widget',
            start(e) {
                data.selectedWidgetIds = [];
                data.selectedWidgetId = null;
            },
            selecting(e) {
                selecting = !fromTemplate;
            },
            stop: function() {
                let focusTab = consts.FOCUS_TABS.PAGE;
                setTimeout(() => {
                    selecting = false;
                }, 100);
                if (data.selectedWidgetIds.length === 1) {
                    const id = data.selectedWidgetIds[0];
                    data.selectedWidgetId = id;
                    focusTab = tool.checkWidgetType(id, dataProvider, () => {
                        this.twinkling();
                    });
                    if (fromTemplate)
                        this.TemplatePropertyPosition(id);
                    }
                root.updateState(data.page.page_id, data.selectedWidgetIds, {focusTab});
            }.bind(this),
            selected(e, ui) {
                const widgetId = $(ui.selected).attr('data-id');
                if (widgetId)
                    storage.addSelectedWidgetId(widgetId);
                }
            });
    },
    isKeyPressed(e) {
        const pressed = (e.shiftKey == 1);
        const shiftKey = pressed
            ? 'shiftKey'
            : '';
        return shiftKey;
    },
    copyWidgets() {
        const root = this.props.root;
        const selectedWidgetIds = storage.data.selectedWidgetIds;
        const widgetsCopy = [];
        for (const i in selectedWidgetIds) {
            const widget_id = selectedWidgetIds[i];
            const selectedWidget = dataProvider.getSpecifyWidgetById(widget_id);
            widgetsCopy.push(selectedWidget);
        }
        storage.data.widgetsCopy = widgetsCopy;
        root.updateMenus.call(null, 'editor');
    },
    pasteWidgets() {
        const root = this.props.root;
        const data = storage.data;
        const widgetsCopy = storage.data.widgetsCopy;
        const page = storage.data.page;
        const offsets = consts.WIDGET_OFFSETS;
        if (widgetsCopy) {
            if ($.isArray(widgetsCopy)) {
                const newCopy = [];
                for (let i = 0; i < widgetsCopy.length; i++) {
                    var copy = $.extend(true, {}, widgetsCopy[i]);
                    copy.offset_x += offsets * 5;
                    copy.offset_y -= offsets * 5;
                    if (copy.type != 16) {
                        copy.type_display = copy.label;
                        copy.form_system = true;
                        copy.id = null;
                        newCopy.push(copy);
                        root.addWidgetToPage(copy);
                    }
                }
                copy = newCopy;
                data.selectedWidgetIds = [];
            } else {
                var copy = $.extend(true, {}, widgetsCopy);
                copy.offset_x += offsets * 5;
                copy.offset_y -= offsets * 5;
                if (copy.type == consts.WIDGET_TYPE.FIXEDBTN) {
                    const canDo = root.canAddFixedBtn();
                    root.updateOverFixedBtnCount(!canDo);
                    if (!canDo)
                        return;
                    }
                if (consts.YIXUN_GAMES_TYPES.indexOf(copy.type) <= -1) {
                    copy.type_display = copy.label;
                    copy.form_system = true;
                    copy.id = null;
                    root.addWidgetToPage(copy);
                }
                data.selectedWidgetId = null;
            }
            storage.data.widgetsCopy = copy;
            root.updateMenus('editor');
        }
    },
    twinkling() {
        const fromTemplate = this.props.fromTemplate;
        if (fromTemplate)
            return false;
        const siderbar = this.elements.editor_right;
        siderbar.addClass('twinkling-animation');
        setTimeout(() => {
            siderbar.removeClass('twinkling-animation');
        }, 1000);
    },
    handleOnContextMenu(el, e) {
        e.preventDefault();
        const data = storage.data;
        const root = this.props.root;
        const offsets = consts.WIDGET_OFFSETS;
        const menuItem = $(e.target || e.srcElement);
        const action = menuItem.attr('data-action');

        if (menuItem.parents('li').hasClass('disabled'))
            return;

        this.elements.canvas.data('context').closemenu();
        if (action) {
            const widgetsCopy = storage.data.widgetsCopy;
            const page = storage.data.page;
            switch (action) {
                case 'paste':
                    if (widgetsCopy) {
                        if ($.isArray(widgetsCopy)) {
                            for (let i = 0; i < widgetsCopy.length; i++) {
                                var copy = $.extend(true, {}, widgetsCopy[i]);
                                copy.offset_x += offsets * 5;
                                copy.offset_y -= offsets * 5;
                                if (copy.type != 16) {
                                    copy.type_display = copy.label;
                                    copy.form_system = true;
                                    copy.id = null;
                                    root.addWidgetToPage(copy);
                                }
                            }
                            data.selectedWidgetIds = [];
                        } else {
                            var copy = $.extend(true, {}, widgetsCopy);
                            copy.offset_x += offsets * 5;
                            copy.offset_y -= offsets * 5;
                            if (copy.type == consts.WIDGET_TYPE.FIXEDBTN) {
                                const canDo = root.canAddFixedBtn();
                                root.updateOverFixedBtnCount(!canDo);
                                if (!canDo)
                                    return;
                                }
                            if (consts.YIXUN_GAMES_TYPES.indexOf(copy.type) <= -1) {
                                copy.type_display = copy.label;
                                copy.form_system = true;
                                copy.id = null;
                                root.addWidgetToPage(copy);
                            }
                            data.selectedWidgetId = null;
                        }
                        storage.data.widgetsCopy = copy;
                        root.updateMenus('editor');
                    }
                    break;
                case 'toggleAll':
                    data.widgetAllVisible = !data.widgetAllVisible;
                    data.toggleAllVisible = data.widgetAllVisible;
                    dataProvider.widgetAllVisibleChanged(data.widgetAllVisible);
                    this.updateSelectedWidget(data.widgetAllVisible);
                    break;
                case 'toggleAllLine':
                    data.toggleAllLineVisible = !data.toggleAllLineVisible;
                    root.updateLineStyle();
                    break;
            }
            root.updateMenus('editor');
            root.updateMenus.call(null, 'widget');
            root.updateWidgets(data.page.page_id, dataProvider.widgets);
        }
        return false;
    },
    updateSelectedWidget(status) {
        const selectedWidget = this.props.selectedWidget;
        const root = this.props.root;
        if (selectedWidget) {
            selectedWidget.visible = status;
            root.setState({selectedWidget});
        }
    },
    updateRulerPosition() {
        const fromTemplate = this.props.fromTemplate;
        if (fromTemplate)
            return false;
        let Ruler = this.refs.Ruler;
        const scale = zoomProvider.scale();
        let left = -this.elements.canvas.position().left / scale,
            top = -this.elements.canvas.position().top / scale;

        const preview = this.props.preview;
        if (preview.showPreview) {
            Ruler = this.refs.preview.refs.Ruler;
        }
        Ruler.updateRulerPosition(left, top);
    },
    TemplatePropertyPosition(id) {
        let viewBox = this.elements.template_property_content,
            totalBox = this.elements.template_content_region,
            item = $(`#${id}`)[0];

        const templateProperty = this.props.parent.refs.mainEditor.refs.rightBar.refs.TemplateProperty;
        templateProperty.updateState('activeTab', 'content'); // 切换至content

        if (!item)
            return false;

        let viewBoxHeight = viewBox.height(),
            totalBoxHeight = totalBox.height(),
            scroll = viewBox.scrollTop(),
            itemTop = $(item).position().top,
            itemHeight = $(item).height(),
            scrollTop = scroll + itemTop - viewBoxHeight / 2 + itemHeight / 2;
        viewBox.scrollTop(scrollTop);
    },
    handleOnPlayVideo(widget) {
        if (widget.type == consts.WIDGET_TYPE.VIDEO) {
            const page = storage.data.page;
            const root = this.props.root;
            widget.pause = !widget.pause;
            root.updateLocaleSelectedWidget(widget);
        }
    },
    deleteSeletedWidget(selectedWidgetId) {
        const root = this.props.root;
        const data = storage.data;
        let results = [];
        if (selectedWidgetId) {
            results = [selectedWidgetId];
        }
        const selectedWidgetIds = data.selectedWidgetIds;
        if (selectedWidgetIds.length) {
            if (selectedWidgetIds.length == 1) {
                if (selectedWidgetIds[0] != results[0]) {
                    data.selectedWidgetIds = [].concat(results);
                } else
                    data.selectedWidgetId = null;
                }
            else {
                results = [].concat(selectedWidgetIds);
            }
        }

        results.forEach((widgetId) => {
            const widget = dataProvider.getSpecifyWidgetById(widgetId);
            if (widget.type == consts.WIDGET_TYPE.REDBAG) {
                root.updateHasRedPacket();
            } else if (widget.type == consts.WIDGET_TYPE.LOOKERS) {
                root.updateHasLookers();
            } else if (widget.type == consts.WIDGET_TYPE.HOPEBANK) {
                root.updateHasHopeBank();
            } else if (widget.type == consts.WIDGET_TYPE.FIXEDBTN) {
                root.updateOverFixedBtnCount(false);
            }
        });
        dataProvider.removeWidgetsByIds(data.page, results, (widgets) => {
            root.setState({widgets, focusTab: consts.FOCUS_TABS.PAGE});
            root.updateSelectedIds(data.page.page_id, results);
            // 触发更新3d场景中组件列表数据
            eventHelper.trigger(consts.EVENTS.THREED_WIDGET_LIST_CHANGED, [consts.DATA_OPERATION.TYPE.DELETE, results]);
        }, root, dataProvider);
    },
    reorderWidgets() { // widgets倒序排列
        const widgets = this.props.widgets;
        widgets.sort(tool.sortBy('sort', true, parseInt));
        return widgets;
    },
    render() {
        const {
            scale,
            widgets,
            preview,
            page,
            fromTemplate,
            selectedWidget,
            centerTop,
            centerLeft,
            switchType
        } = this.props;
        const rStyle = {
            WebkitTransformOrigin: '50% 50%',
            MozTransform: `scale(${scale})`,
            WebkitTransform: `scale(${scale})`
        };

        let previewNode = '';
        if (preview.showPreview) {
            previewNode = <Preview top={centerTop} left={centerLeft} transform={this.transform} preview={preview} root={root} fromTemplate={fromTemplate} page={page} switchType={switchType} style={rStyle} ref="preview"/>;
        }

        const BoxStyle = {
            left: !fromTemplate
                ? '65px'
                : '0px'
        };

        let RulerNode = '';
        if (!fromTemplate && !preview.showPreview) {
            RulerNode = <Ruler/>;
        }

        return (
            <div>
                <div id="moving_box" ref="container" data-drop-containment className={`${switchType == consts.SWITCH_TYPE.THREED_AR
                    ? 'hidden-status'
                    : 'visible-status'} creator-panel creator-editor drop-containment editorquyu`} onScroll={this.updateRulerPosition} style={BoxStyle}>
                    <div style={rStyle} className="editor-canvas editor_test editor_hidden ui-selectable" data-editor-canvas aria-disabled="false">
                        <Phone switchType={switchType} showSnap="true" root={root} page={page}/>
                        <img className="editor-main-img" style={{
                            display: consts.SWITCH_TYPE.H5_AR === switchType
                                ? 'none'
                                : 'none'
                        }} src={storage.data.CONST.media_src} width="480"/>
                        <div className="snap_theme"/>
                        <div className="lineCanvas"/> {widgets.map((widget) => {
                            if (selectedWidget.id === widget.id) {
                                widget = selectedWidget;
                            }
                            if (widget.type !== consts.WIDGET_TYPE.FIXEDBTN) {
                                return <Widget ref="widget" key={`${widget.id}-m`} transform={this.transform} root={root} widget={widget} fromTemplate={fromTemplate} parent={this}/>;
                            } else {
                                return null;
                            }
                        })
}
                        {RulerNode}
                    </div>
                    <div className="creator-panel editor-path-canvas" data-path-canvas style={rStyle}/> {previewNode}
                </div>
            </div>
        );
    }
});

Editor.propTypes = {
    scale: React.PropTypes.number,
    preview: React.PropTypes.object,
    widgets: React.PropTypes.widgets,
    centerTop: React.PropTypes.number,
    centerLeft: React.PropTypes.number,
    switchType: React.PropTypes.string
};

Editor.defaultProps = {
    scale: 1,
    preview: {},
    widgets: [],
    centerTop: 0,
    centerLeft: 0,
    switchType: ''
};

module.exports = Editor;
